#include "DiagramBlock.h"
#include "Control.h"
#include <iostream>
#include <string>

using namespace llvm;

DiagramBlock::DiagramBlock(std::string name, bool topLevel) : NodeContainer(), name(name) {
  isTopLevel=topLevel;
}


void DiagramBlock::add(Node* child) {
  addNode(child);
  if (child->isIO()) {
    diagramIOs.push_back((Control*)child);
  }
}

Module* DiagramBlock::process() {
  
  LLVMContext &Context = getGlobalContext();
  Module *TheModule = new Module("Module",Context);

  Function *F;
  if (isTopLevel) {
    for (int i=0;i<diagramIOs.size();i++) {
      std::string name("IO");
      name+=std::to_string(i);
      diagramIOs[i]->setValue(TheModule->getOrInsertGlobal(name,Type::getInt32Ty(Context)));
    }
    FunctionType *FT = FunctionType::get(Type::getVoidTy(Context), false);
    F = Function::Create(FT, Function::ExternalLinkage, name, TheModule);
  } else {
    std::vector<Type*> Pointers(diagramIOs.size(), Type::getInt32PtrTy(Context));
    FunctionType *FT = FunctionType::get(Type::getVoidTy(Context), Pointers, false);
    F = Function::Create(FT, Function::ExternalLinkage, name, TheModule);
    int i=0;
    for (Function::arg_iterator AI = F->arg_begin(); i < diagramIOs.size(); ++AI, ++i) {
      std::string name("IO");
      name+=std::to_string(i);
      AI->setName(name);
      diagramIOs[i]->setValue(AI);
    } 
  }
  IRBuilder<> builder(Context);
  BasicBlock *bb = BasicBlock::Create(Context, "im_in_ur_function", F);
  builder.SetInsertPoint(bb);
  processNodes(&builder);
  builder.CreateRetVoid();
  return TheModule;
}
